home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / multiprocessing / process.py < prev    next >
Text File  |  2009-11-02  |  8KB  |  298 lines

  1. #
  2. # Module providing the `Process` class which emulates `threading.Thread`
  3. #
  4. # multiprocessing/process.py
  5. #
  6. # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
  7. #
  8.  
  9. __all__ = ['Process', 'current_process', 'active_children']
  10.  
  11. #
  12. # Imports
  13. #
  14.  
  15. import os
  16. import sys
  17. import signal
  18. import itertools
  19.  
  20. #
  21. #
  22. #
  23.  
  24. try:
  25.     ORIGINAL_DIR = os.path.abspath(os.getcwd())
  26. except OSError:
  27.     ORIGINAL_DIR = None
  28.  
  29. #
  30. # Public functions
  31. #
  32.  
  33. def current_process():
  34.     '''
  35.     Return process object representing the current process
  36.     '''
  37.     return _current_process
  38.  
  39. def active_children():
  40.     '''
  41.     Return list of process objects corresponding to live child processes
  42.     '''
  43.     _cleanup()
  44.     return list(_current_process._children)
  45.  
  46. #
  47. #
  48. #
  49.  
  50. def _cleanup():
  51.     # check for processes which have finished
  52.     for p in list(_current_process._children):
  53.         if p._popen.poll() is not None:
  54.             _current_process._children.discard(p)
  55.  
  56. #
  57. # The `Process` class
  58. #
  59.  
  60. class Process(object):
  61.     '''
  62.     Process objects represent activity that is run in a separate process
  63.  
  64.     The class is analagous to `threading.Thread`
  65.     '''
  66.     _Popen = None
  67.  
  68.     def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
  69.         assert group is None, 'group argument must be None for now'
  70.         count = _current_process._counter.next()
  71.         self._identity = _current_process._identity + (count,)
  72.         self._authkey = _current_process._authkey
  73.         self._daemonic = _current_process._daemonic
  74.         self._tempdir = _current_process._tempdir
  75.         self._parent_pid = os.getpid()
  76.         self._popen = None
  77.         self._target = target
  78.         self._args = tuple(args)
  79.         self._kwargs = dict(kwargs)
  80.         self._name = name or type(self).__name__ + '-' + \
  81.                      ':'.join(str(i) for i in self._identity)
  82.  
  83.     def run(self):
  84.         '''
  85.         Method to be run in sub-process; can be overridden in sub-class
  86.         '''
  87.         if self._target:
  88.             self._target(*self._args, **self._kwargs)
  89.  
  90.     def start(self):
  91.         '''
  92.         Start child process
  93.         '''
  94.         assert self._popen is None, 'cannot start a process twice'
  95.         assert self._parent_pid == os.getpid(), \
  96.                'can only start a process object created by current process'
  97.         assert not _current_process._daemonic, \
  98.                'daemonic processes are not allowed to have children'
  99.         _cleanup()
  100.         if self._Popen is not None:
  101.             Popen = self._Popen
  102.         else:
  103.             from .forking import Popen
  104.         self._popen = Popen(self)
  105.         _current_process._children.add(self)
  106.  
  107.     def terminate(self):
  108.         '''
  109.         Terminate process; sends SIGTERM signal or uses TerminateProcess()
  110.         '''
  111.         self._popen.terminate()
  112.  
  113.     def join(self, timeout=None):
  114.         '''
  115.         Wait until child process terminates
  116.         '''
  117.         assert self._parent_pid == os.getpid(), 'can only join a child process'
  118.         assert self._popen is not None, 'can only join a started process'
  119.         res = self._popen.wait(timeout)
  120.         if res is not None:
  121.             _current_process._children.discard(self)
  122.  
  123.     def is_alive(self):
  124.         '''
  125.         Return whether process is alive
  126.         '''
  127.         if self is _current_process:
  128.             return True
  129.         assert self._parent_pid == os.getpid(), 'can only test a child process'
  130.         if self._popen is None:
  131.             return False
  132.         self._popen.poll()
  133.         return self._popen.returncode is None
  134.  
  135.     @property
  136.     def name(self):
  137.         return self._name
  138.  
  139.     @name.setter
  140.     def name(self, name):
  141.         assert isinstance(name, str), 'name must be a string'
  142.         self._name = name
  143.  
  144.     @property
  145.     def daemon(self):
  146.         '''
  147.         Return whether process is a daemon
  148.         '''
  149.         return self._daemonic
  150.  
  151.     @daemon.setter
  152.     def daemon(self, daemonic):
  153.         '''
  154.         Set whether process is a daemon
  155.         '''
  156.         assert self._popen is None, 'process has already started'
  157.         self._daemonic = daemonic
  158.  
  159.     @property
  160.     def authkey(self):
  161.         return self._authkey
  162.  
  163.     @authkey.setter
  164.     def authkey(self, authkey):
  165.         '''
  166.         Set authorization key of process
  167.         '''
  168.         self._authkey = AuthenticationString(authkey)
  169.  
  170.     @property
  171.     def exitcode(self):
  172.         '''
  173.         Return exit code of process or `None` if it has yet to stop
  174.         '''
  175.         if self._popen is None:
  176.             return self._popen
  177.         return self._popen.poll()
  178.  
  179.     @property
  180.     def ident(self):
  181.         '''
  182.         Return indentifier (PID) of process or `None` if it has yet to start
  183.         '''
  184.         if self is _current_process:
  185.             return os.getpid()
  186.         else:
  187.             return self._popen and self._popen.pid
  188.  
  189.     pid = ident
  190.  
  191.     def __repr__(self):
  192.         if self is _current_process:
  193.             status = 'started'
  194.         elif self._parent_pid != os.getpid():
  195.             status = 'unknown'
  196.         elif self._popen is None:
  197.             status = 'initial'
  198.         else:
  199.             if self._popen.poll() is not None:
  200.                 status = self.exitcode
  201.             else:
  202.                 status = 'started'
  203.  
  204.         if type(status) is int:
  205.             if status == 0:
  206.                 status = 'stopped'
  207.             else:
  208.                 status = 'stopped[%s]' % _exitcode_to_name.get(status, status)
  209.  
  210.         return '<%s(%s, %s%s)>' % (type(self).__name__, self._name,
  211.                                    status, self._daemonic and ' daemon' or '')
  212.  
  213.     ##
  214.  
  215.     def _bootstrap(self):
  216.         from . import util
  217.         global _current_process
  218.  
  219.         try:
  220.             self._children = set()
  221.             self._counter = itertools.count(1)
  222.             try:
  223.                 sys.stdin.close()
  224.                 sys.stdin = open(os.devnull)
  225.             except (OSError, ValueError):
  226.                 pass
  227.             _current_process = self
  228.             util._finalizer_registry.clear()
  229.             util._run_after_forkers()
  230.             util.info('child process calling self.run()')
  231.             try:
  232.                 self.run()
  233.                 exitcode = 0
  234.             finally:
  235.                 util._exit_function()
  236.         except SystemExit, e:
  237.             if not e.args:
  238.                 exitcode = 1
  239.             elif type(e.args[0]) is int:
  240.                 exitcode = e.args[0]
  241.             else:
  242.                 sys.stderr.write(e.args[0] + '\n')
  243.                 sys.stderr.flush()
  244.                 exitcode = 1
  245.         except:
  246.             exitcode = 1
  247.             import traceback
  248.             sys.stderr.write('Process %s:\n' % self.name)
  249.             sys.stderr.flush()
  250.             traceback.print_exc()
  251.  
  252.         util.info('process exiting with exitcode %d' % exitcode)
  253.         return exitcode
  254.  
  255. #
  256. # We subclass bytes to avoid accidental transmission of auth keys over network
  257. #
  258.  
  259. class AuthenticationString(bytes):
  260.     def __reduce__(self):
  261.         from .forking import Popen
  262.         if not Popen.thread_is_spawning():
  263.             raise TypeError(
  264.                 'Pickling an AuthenticationString object is '
  265.                 'disallowed for security reasons'
  266.                 )
  267.         return AuthenticationString, (bytes(self),)
  268.  
  269. #
  270. # Create object representing the main process
  271. #
  272.  
  273. class _MainProcess(Process):
  274.  
  275.     def __init__(self):
  276.         self._identity = ()
  277.         self._daemonic = False
  278.         self._name = 'MainProcess'
  279.         self._parent_pid = None
  280.         self._popen = None
  281.         self._counter = itertools.count(1)
  282.         self._children = set()
  283.         self._authkey = AuthenticationString(os.urandom(32))
  284.         self._tempdir = None
  285.  
  286. _current_process = _MainProcess()
  287. del _MainProcess
  288.  
  289. #
  290. # Give names to some return codes
  291. #
  292.  
  293. _exitcode_to_name = {}
  294.  
  295. for name, signum in signal.__dict__.items():
  296.     if name[:3]=='SIG' and '_' not in name:
  297.         _exitcode_to_name[-signum] = name
  298.